package com.tanhua.dubbo.es.api;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.dubbo.config.annotation.Service;
import com.tanhua.dubbo.server.api.UserLocationApi;
import com.tanhua.dubbo.server.pojo.UserLocation;
import com.tanhua.dubbo.server.pojo.UserLocation_Mongo;
import com.tanhua.dubbo.server.vo.UserLocationVo;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
@Slf4j
public class UserLocationApiImpl implements UserLocationApi {

    @Autowired
    private MongoTemplate mongoTemplate;


    //mongo实现更新地理信息;
    public Boolean updateUserLocation1(Long userId, Double longitude, Double latitude, String address) {
        try {
            org.springframework.data.mongodb.core.query.Query query = org.springframework.data.mongodb.core.query.Query.query(Criteria.where("userId").is(userId));
            UserLocation_Mongo userLocation_mongo = mongoTemplate.findOne(query, UserLocation_Mongo.class);
            if (ObjectUtil.isEmpty(userLocation_mongo)){
                //执行添加
                userLocation_mongo = new UserLocation_Mongo();
                userLocation_mongo.setUserId(userId);
                userLocation_mongo.setLocation(new GeoJsonPoint(longitude , latitude));
                userLocation_mongo.setAddress(address);
                userLocation_mongo.setCreated(System.currentTimeMillis());
                userLocation_mongo.setUpdated(userLocation_mongo.getCreated());
                userLocation_mongo.setLastUpdated(userLocation_mongo.getUpdated());
                userLocation_mongo.setId(ObjectId.get());

                mongoTemplate.insert(userLocation_mongo);
            }else{
                GeoJsonPoint geo = new GeoJsonPoint(longitude , latitude);
                Update update = Update.update("location", geo);
                update.set("address" , address)
                        .set("updated" , System.currentTimeMillis())
                        .set("lastUpdated" , userLocation_mongo.getUpdated());
                mongoTemplate.upsert(query , update , UserLocation_Mongo.class);
            }
            return true;
        } catch (Exception e) {
            log.error("更新地理位置失败~ userId = " + userId + ", longitude = " + longitude + ", latitude = " + latitude + ", address = " + address, e);
        }
        return false;   //更新地理信息失败
    }

    //mongo实现查询用户地理信息
    public UserLocationVo queryByUserId1(Long userId) {
        Query query = Query.query(Criteria.where("userId").is(userId));
        UserLocation_Mongo userLocation_mongo = mongoTemplate.findOne(query, UserLocation_Mongo.class);
        return UserLocationVo.format(userLocation_mongo);
    }

    //mongodb实现搜附近
    public List<UserLocationVo> queryUserFromLocation1(Double longitude, Double latitude, Double distance, Integer page, Integer pageSize) {
        Point point = new Point(longitude , latitude);
        Circle circle = new Circle(point , new Distance(distance/100 , Metrics.KILOMETERS));
        PageRequest pageRequest = PageRequest.of(page-1 , pageSize , Sort.by(Sort.Order.asc("location")));
        Query query = Query.query(Criteria.where("location").withinSphere(circle)).with(pageRequest);
        List<UserLocation_Mongo> userLocation_mongos = mongoTemplate.find(query, UserLocation_Mongo.class);
        return UserLocationVo.formatToList1(userLocation_mongos);
    }

}
